<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue</title>
    <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <div v-html="message"></div>
</div>

<div id="author"></div>
<author></author>

<script>
    var vm = new Vue({
        el: '#app', //vm.$el
        data: { //vm.$data
            message: '<h1>菜鸟教程</h1>'
        }
    })


    //选热爱函数 &jsx


    //全局配置
    //Vue.config 是一个对象， 包含Vue的全局配置。
    1.Vue.config.silent = ture ;//取消Vue所有的日志与警告
    2.optionMergeStratrgies 类型 ：{[key : string] : function}
        Vue.config.optionMergeStrategies._my_option = function( parent(父实例), child(子实例), vm(Vue 实例上下文被作为第三个参数传入)){
            return child + 1
        }
        const profile = Vue.extends({
            _my_option : 1
        })
        自定义合并策略的选项
    3.devtools
        Vue.config.devtools = true(配置是否允许 vue-devtools 检查代码。开发版本默认为 true，生产版本默认为 false。)
    4.errorHandler
        Vue.config.errorHandler = function(err, vm, info){

        }
        指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时， 可获取错误信息和Vue实例
    5.（待补充0）

    二、全局API
    1、Vue.extend(options)
        使用基础Vue构造器吗，创建一个“子类”。参数是一个包含组件选项的对象(data 选项是特列， 其必须是函数)
//        <div id="mount-point"></div>
//        // 创建构造器
//        var Profile = Vue.extend({
//            template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
//            data: function () {
//                return {
//                    firstName: 'Walter',
//                    lastName: 'White',
//                    alias: 'Heisenberg'
//                }
//            }
//        })
//        // 创建 Profile 实例，并挂载到一个元素上。
//        new Profile().$mount('#mount-point')
//        结果如下：
//
//        <p>Walter White aka Heisenberg</p>
    2、Vue.$nextTick([callback, context])
        在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法，获取更新后的DOM
    3、Vue.set(target, key, value)
        设置对象的属性。如果对象是响应的，确保属性被创建后也是响应的，同时触发视图更新。这个方法主要用于避开Vue不能检测属性被添加的限制
    4.Vue.delete(target, key)
        删除对象的属性。如果对象是响应式的，确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到属性被删除的限制，但是你应该很少会使用它。
    5、Vue.directive(id, [definition]->{Function | Object} [definition] )
        注册或获取全局指令
//        Vue.directive('my-directive', {
//            bind: function () {},
//            inserted: function () {},
//            update: function () {},
//            componentUpdated: function () {},
//            unbind: function () {}
//        })
//        // 注册 (指令函数)
//        Vue.directive('my-directive', function () {
//            // 这里将会被 `bind` 和 `update` 调用
//        })
//        // getter，返回已注册的指令
//        var myDirective = Vue.directive('my-directive')
    6.Vue.filter(id, [definition]->{function [definition]})
        注册或获取全局过滤器
    // 注册
//        Vue.filter('my-filter', function (value) {
//            // 返回处理后的值
//        })
//        // getter，返回已注册的过滤器
//        var myFilter = Vue.filter('my-filter')
    7.Vue.component(id,[definition])
        注册或获取全局组件。注册还会自动使用给定的id设置组件的名称
//        // 注册组件，传入一个扩展过的构造器
//        Vue.component('my-component', Vue.extend({ /* ... */ }))
//        // 注册组件，传入一个选项对象 (自动调用 Vue.extend)
//        Vue.component('my-component', { /* ... */ })
//        // 获取注册的组件 (始终返回构造器)
//        var MyComponent = Vue.component('my-component')
    8.Vue.use(plugin -> {Object | Function} )
        安装Vue.js插件。如果插件是一个对象，必须提供install 方法。如果插件是一个函数，它会被作为install方法。install方法将被作为Vue的参数调用
    9.Vue.mixin(mixin -> {Object})
        全局注册一个混合，影响注册之后所有创建的每个Vue实例。
    10.Vue.compile(template {string})
        在render函数中编译模板字符串。只独立构建时有效
//        var res = Vue.compile('<div><span>{{ msg }}</span></div>')
//        new Vue({
//            data: {
//                msg: 'hello'
//            },
//            render: res.render,
//            staticRenderFns: res.staticRenderFns
//        })
    11.Vue.version
        提供字符串形式的 Vue 安装版本号。这对社区的插件和组件来说非常有用，你可以根据不同的版本号采取不同的策略。
    //    var version = Number(Vue.version.split('.')[0])
    //    if (version === 2) {
    //        // Vue v2.x.x
    //    } else if (version === 1) {
    //        // Vue v1.x.x
    //    } else {
    //        // Unsupported versions of Vue
    //    }
    三、数据
        1.data
    //    var data = { a: 1 }
    //    // 直接创建一个实例
    //    var vm = new Vue({
    //        data: data
    //    })
    //    vm.a // => 1
    //    vm.$data === data // => true
    //    // Vue.extend() 中 data 必须是函数
    //    var Component = Vue.extend({
    //        data: function () {
    //            return { a: 1 }
    //        }
    //    })
        2.props  -> Array<string> | Object
            props 可以是数组或对象，用于接收来自父组件的数据。props 可以是简单的数组，或者使用对象作为替代，对象允许配置高级选项，如类型检测、自定义校验和设置默认值。
//        // 简单语法
//        Vue.component('props-demo-simple', {
//            props: ['size', 'myMessage']
//        })
//        // 对象语法，提供校验
//        Vue.component('props-demo-advanced', {
//            props: {
//                // 检测类型
//                height: Number,
//                // 检测类型 + 其他验证
//                age: {
//                    type: Number, 基础类型检测 ‘null’任何类型都可以
//                    default: 0, 默认值
//                    required: true, 必传
//                    validator: function (value) { // 自定义验证函数
//                        return value >= 0
//                    }
//                }
//            }
//        })
        3.propsData -> {[key:sting] ：any} 只用于new创建的实例中
            创建实例时传递 props。主要作用是方便测试
//            var Comp = Vue.extend({
//                props: ['msg'],
//                template: '<div>{{ msg }}</div>'
//            })
//            var vm = new Comp({
//                propsData: {
//                    msg: 'hello'
//                }
//            })
        4.computed() ->{[key : string] : function | {get : function, set : function}}
            计算属性将混入到Vue实例中。所有getter和setter的this上下文自动地绑定未Vue实例
//            var vm = new Vue({
//                data: { a: 1 },
//                computed: {
//                    // 仅读取
//                    aDouble: function () {
//                        return this.a * 2
//                    },
//                    // 读取和设置
//                    aPlus: {
//                        get: function () {
//                            return this.a + 1
//                        },
//                        set: function (v) {
//                            this.a = v - 1
//                        }
//                    }
//                }
//            })
//            vm.aPlus   // => 2
//            vm.aPlus = 3
//            vm.a       // => 2
//            vm.aDouble // => 4
        5.methods -> {[key : string] :function}
            methods将被混入到Vue实例中。可以直接通过VM实例访问这些方法，或者在指令表达式中使用。方法中的this自动绑定为Vue实例
//            var vm = new Vue({
//                data: { a: 1 },
//                methods: {
//                    plus: function () {
//                        this.a++
//                    }
//                }
//            })
//            vm.plus()
//            vm.a // 2
        6.watch -> {[key : string]: string | function | object}
            一个对象，键是需要观察的表达式，值式对应回调函数。值也可以式方法名，或者包含选项的对象。Vue实例将会实例化时调用$watch()， 遍历watch对象的每一个属性
//            var vm = new Vue({
//                data: {
//                    a: 1,
//                    b: 2,
//                    c: 3,
//                    d: 4
//                },
//                watch: {
//                    a: function (val, oldVal) {
//                        console.log('new: %s, old: %s', val, oldVal)
//                    },
//                    // 方法名
//                    b: 'someMethod',
//                    // 深度 watcher
//                    c: {
//                        handler: function (val, oldVal) { /* ... */ },
//                        deep: true
//                    },
//                    // 该回调将会在侦听开始之后被立即调用
//                    d: {
//                        handler: function (val, oldVal) { /* ... */ },
//                        immediate: true
//                    }
//                }
//            })
//            vm.a = 2 // => new: 2, old: 1
        四、DOM
            1. #el(vm.$el )
                只在 new 创建的实例中遵守。 vm.$mount()手动开始编译
            2.template  ->

            3.render -> (createElement ： () =>VNode) => VNode
                字符串模板的替代方案，允许你发挥 JavaScript 最大的编程能力，该渲染函数接收一个createElement 方法作为第一个参数用来创建 vNode
                如果组件是一个函数组件，渲染函数还会接收一个额外的 context参数， 为没有实例的函数组件提供上下为信息
                （Vue选项中render函数若存在，则Vue构造函数不会从template选项或通过el选项指定的挂载元素中提出的html模板渲染函数）
            4.renderError -> （createElement :() => VNode, error: Error）=> VNode 只在开发环境下工作 当render函数遭遇错时，提供另外一种渲染方式
//            new Vue({
//                render (h) {
//                    throw new Error('oops')
//                },
//                renderError (h, err) {
//                    return h('pre', { style: { color: 'red' }}, err.stack)
//                }
//            }).$mount('#app')
        五、生命周期钩子


        六、资源
            1.directives
            包含Vue实例可用指令的哈希表
            2.filters
                包含Vue实例可用过滤器的哈希表
            3.components
                包含Vue实例可用组件的哈希表
        七、组合
            1.parent
                指定已创建的实例之父实例，在二者之间建立父子关系。子实例可用用 this.$parent 访问父实例，子实例被推入父实例的 $children数组中
            2.minins
             接受一个混合对象的数组。这些混合实例对象可用像正常的实例对象一样包含选项，他们将在Vue.extends()里面最终选择使用相同的选项合并逻辑合并。
                Minin钩子按照传入顺序依次调用， 并在调用组件自身的钩子之前被调用。
//                    var mixin = {
//                        created: function () { console.log(1) }
//                    }
//                    var vm = new Vue({
//                        created: function () { console.log(2) },
//                        mixins: [mixin]
//                    })
//                    // => 1
    // => 2
            3.extends -> Objecet | function
                允许声明扩展另一个组件（一个简单的选项对象或者构造函数）,而无需使用Vue.extends。主要便于扩展单文件组件（和mixins类似）,区别在于，组件自身1选项会比要扩展的源组件具有更高的优先级
        //    var CompA = { ... }
        //    // 在没有调用 `Vue.extend` 时候继承 CompA
        //    var CompB = {
        //        extends: CompA,
        //        ...
        //    }
            4.provide/inject
                主要为高级插件/组件库提供用列，
//            var Provider = {
//                provide: {
//                    foo: 'bar'
//                },
//                // ...
//            }
//            var Child = {
//                inject: ['foo'],
//                created () {
//                    console.log(this.foo) // => "bar"
//                }
//                // ...
//            }
        八、其他
            1.name
            2.delimiters
            3.functional
            4.model  ->{prop? :string, event?string}
                允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下，一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event，但是一些输入类型比如单选框和复选框按钮可能像使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突
//            Vue.component('my-checkbox', {
//                model: {
//                    prop: 'checked',
//                    event: 'change'
//                },
//                props: {
//                    // this allows using the `value` prop for a different purpose
//                    value: String,
//                    // use `checked` as the prop which take the place of `value`
//                    checked: {
//                        type: Number,
//                        default: 0
//                    }
//                },
//                // ...
//            })
//            <my-checkbox v-model="foo" value="some value"></my-checkbox>
//            上述代码相当于：
//
//            <my-checkbox
//            :checked="foo"
//            @change="val => { foo = val }"
//            value="some value">
//                </my-checkbox>


    实例属性

    1.vm.$data
    2.vm.$props
    3.vm.$el
    4.vm.$options 用于当前Vue实例的初始化选项。需要在选项中包含自定义属性时
    5.vm.$parent 父实例
    6.vm.$children  当前实例的直接子组件。需要注意$children
    7.vm.$slots ->{[name:string] : ?Array<VNode>}
        用来访问被插槽分发的内容。每个具名插槽 有其相应的属性 (例如：slot="foo" 中的内容将会在 vm.$slots.foo 中被找到)。default 属性包括了所有没有被包含在具名插槽中的节点。
    8.vm.$scopedSlots
    9.vm.$refs
    10.vm.$isServer
    11.vm.$attrs
       包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时，这里会包含所有父作用域的绑定 (class 和 style 除外)，并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用。
    12.vm.$listeners
    包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

    实例方法/数据
    1.vm.$watch(expOrFn, callback, [options])
        观察Vue实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式，用一个函数代替
        a.deep 为了发现对象内部值的变化，可以在选项参数中指定deep：true。
    // 键路径
//        vm.$watch('a.b.c', function (newVal, oldVal) {
                deep：true,
                immediate:true 将立即以表达式的当前值触发回调
//            // 做点什么
//        })
//        // 函数
//        vm.$watch(
//            function () {
//                return this.a + this.b
//            },
//            function (newVal, oldVal) {
//                // 做点什么
//            }
//        )
//        vm.$watch 返回一个取消观察函数，用来停止触发回调：
//
//    var unwatch = vm.$watch('a', cb)
//        // 之后取消观察
//        unwatch()
    2.vm.$set(target, key, value)
    3.vm.$delete(target, key)

    实例方法/事件
    1.vm.$on(event,callback)
        监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数将会接收所有传入事触发函数的额外参数
//        vm.$on('test', function (msg) {
//            console.log(msg)
//        })
//        vm.$emit('test', 'hi')
//        // => "hi"
    2.vm.$once(event,callback)
        监听一自定义事件，但是只触发一次，在第一次触发之后移除监听器
    3.vm.$off([event,callback])
        移除自定义事件监听器。（如果没有提供参数，则移除所有的事件监听器；如果只提供了事件，则移除该事件所有的监听器；如果同时提供了事件与回调，则只移除这个回调的监听器）
    4.vm.$emit(event,[..args])
        触发当前实例上的事件，附加参数都会传给监听器回调

    实例方法/生命活动
    1.vm.$mount([elemtOrSelector]) 返回 vm -实例自身
         如果 Vue 实例在实例化时没有收到 el 选项，则它处于“未挂载”状态，没有关联的 DOM 元素。可以使用 vm.$mount() 手动地挂载一个未挂载的实例。
    2.vm.$forceUpdate() 使Vue重新渲染。仅仅影响实例本身和插入插槽内容的子组件，而不是所有子组件
    3.vm.$nextTick([callback])
        将回调延迟到下次DOM更新循环之后执行。在修改数据之后立即使用它，然后等待DOM更新。它跟全局方法Vue.nextTick 一样，不同的是回调的this自动绑定到调用它的实例上
    4.vm.$destroy()完全销毁一个实例，清理它与其它实例的链接，解绑它的全部指令及事件监听器

    指令
    1.v-text 更新元素的textCountent. 如果要更新部分的textContent， 需要使用{{Mustache}}的值
         <span v-text="msg"></span>
        <!-- 和下面的一样 -->
        <span>{{msg}}</span>
    2.v-html 更新元素的 innerHtml （内容按普通HTML插入-不会作为Vue模板插入）只在可信内容上使用 v-html，永不用在用户提交的内容上
        <div v-html="html"></div>
    3.v-show 根据表达式之真假的， 切换元素的display CSS属性
    4.v-if 根据表达式的值的真假条件渲染元素， 在切换元素及它的数据绑定/组件被销毁并重建，如果元素是<template>,将提出它的内容作为条件块
    5.v-else
    6.v-else-if
    7.v-for
        <div v-for="item in items">
        {{ item.text }}
        </div>
    8.v-on 缩写 @  绑定事件
        修饰符：
        .stop - 调用 event.stopPropagation()。
        .prevent - 调用 event.preventDefault()。
        .capture - 添加事件侦听器时使用 capture 模式。
        .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
        .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
        .native - 监听组件根元素的原生事件。
        .once - 只触发一次回调。
        .left - (2.2.0) 只当点击鼠标左键时触发。
        .right - (2.2.0) 只当点击鼠标右键时触发。
        .middle - (2.2.0) 只当点击鼠标中键时触发。
        .passive - (2.3.0) 以 { passive: true } 模式添加侦听器
    9.v-bind 缩写 ： 动态地绑定一个或多个特性，或一个组件 prop 到表达式。
        ··修饰符：
        .prop - 被用于绑定 DOM 属性 (property)。(差别在哪里？)
        .camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase. (从 2.1.0 开始支持)
        .sync (2.3.0+) 语法糖，会扩展成一个更新父组件绑定值的 v-on 侦听器。
        <!-- 通过 prop 修饰符绑定 DOM 属性 -->
        <div v-bind:text-content.prop="text"></div>
            <!-- prop 绑定。“prop”必须在 my-component 中声明。-->
            <my-component :prop="someThing"></my-component>
            <!-- 通过 $props 将父组件的 props 一起传给子组件 -->
            <child-component v-bind="$props"></child-component>
            <!-- XLink -->
            <svg><a :xlink:special="foo"></a></svg>
    10.v-model 在表单控件或者组件上创建双向绑定。细节请看下面的教程链接。
            限制： <input>  <select> <textarea> components
            修饰符：
            .lazy - 取代 input 监听 change 事件
            .number - 输入字符串转为数字
            .trim - 输入首尾空格过滤
    11.v-pre跳过这个元素和它的子元素的编译过程，可以用来显示元素的Mustache标签， 跳过大量没有指令的节点会加快编译
    <span v-pre>{{  不会编译这部分}}</span>
    12.v-once z只渲染元素和组件一次。随后的重新渲染，元素/组件及其所有子节点将被视为静态内容跳过， 优化更新性能
        <!-- 单个元素 -->
        <span v-once>This will never change: {{msg}}</span>
        <!-- 有子元素 -->
        <div v-once>
        <h1>comment</h1>
        <p>{{msg}}</p>
        </div>
        <!-- 组件 -->
        <my-component v-once :comment="msg"></my-component>
            <!-- `v-for` 指令-->
            <ul>
            <li v-for="i in list" v-once>{{i}}</li>
        </ul>

    特殊特性

        1.key  ->number | String
            key的特殊属性主要用在Vue的虚拟DOM算法，在新旧nodes对比时辨识VNodes，如果不使用key，Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/在利益相同类型元素的算法。使用key，它会基于key的变化重新排序元素顺序，并且会移除key不存在的元素
            有相同父元素的子元素必须有独特的key，重复的key会造成渲染错误
            <ul>
            <li v-for="item in items" :key="item.id">...</li>
            </ul>
            它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用：

            完整地触发组件的生命周期钩子
            触发过渡
            例如：

            <transition>
            <span :key="text">{{ text }}</span>
            </transition>
            当 text 发生改变时，<span> 会随时被更新，因此会触发过渡
        2.ref ->string
            ref被用来给元素或子组件注册引用信息，引用信息将会注册父组件的$refs对象上。如果在普通的DOM元素上使用，引用指向的就是DOM元素；如果用在子组件上，引用就指向组件实例
            <!-- vm.$refs.p will be the DOM node -->
            <p ref="p">hello</p>
                <!-- vm.$refs.child will be the child comp instance -->
                <child-comp ref="child"></child-comp>
        3.solt ->String
            用于标记往哪个具名插槽中插入子组件内容
        4.solt-scope
        5.is 用于动态组件且基于 DOM内模板的来工作
            <!-- component changes when currentView changes -->
            <component v-bind:is="currentView"></component>
                <!-- necessary because `<my-row>` would be invalid inside -->
                <!-- a `<table>` element and so would be hoisted out      -->
                <table>
                <tr is="my-row"></tr>
                </table>
    内置的组件
        1.component 渲染一个"元组件"为动态组件。依 is 的值，来决定哪个组件被渲染
            <!-- 动态组件由 vm 实例的属性值 `componentId` 控制 -->
            <component :is="componentId"></component>
            <!-- 也能够渲染注册过的组件或 prop 传入的组件 -->


    2.transition

            Props：

        name - string，用于自动生成 CSS 过渡类名。例如：name: 'fade' 将自动拓展为.fade-enter，.fade-enter-active等。默认类名为 "v"
            appear - boolean，是否在初始渲染时使用过渡。默认为 false。
        css - boolean，是否使用 CSS 过渡类。默认为 true。如果设置为 false，将只通过组件事件触发注册的 JavaScript 钩子。
        type - string，指定过渡事件类型，侦听过渡何时结束。有效值为 "transition" 和 "animation"。默认 Vue.js 将自动检测出持续时间长的为过渡事件类型。
        mode - string，控制离开/进入的过渡时间序列。有效的模式有 "out-in" 和 "in-out"；默认同时生效。
        enter-class - string
            leave-class - string
            appear-class - string
            enter-to-class - string
            leave-to-class - string
            appear-to-class - string
            enter-active-class - string
            leave-active-class - string
            appear-active-class - string
            事件：

        before-enter
            before-leave
            before-appear
            enter
            leave
            appear
            after-enter
            after-leave
            after-appear
            enter-cancelled
            leave-cancelled (v-show only)
            appear-cancelled
            用法：

            <transition> 元素作为单个元素/组件的过渡效果。<transition> 只会把过渡效果应用到其包裹的内容上，而不会额外渲染 DOM 元素，也不会出现在检测过的组件层级中。

            <!-- 简单元素 -->
            <transition>
            <div v-if="ok">toggled content</div>
            </transition>
            <!-- 动态组件 -->
            <transition name="fade" mode="out-in" appear>
            <component :is="view"></component>
                </transition>
                <!-- 事件钩子 -->
                <div id="transition-demo">
                <transition @after-enter="transitionComplete">
                <div v-show="ok">toggled content</div>
            </transition>
            </div>

            new Vue({
                ...
                    methods: {
                transitionComplete: function (el) {
                    // 传入 'el' 这个 DOM 元素作为参数。
                }
            }
            ...
            }).$mount('#transition-demo')
    /script>

        2.transition-group
        3.keep-alive
        3.solt
            Props
            name - string，用于命名插槽。
            Usage：

            <slot> 元素作为组件模板之中的内容分发插槽。<slot> 元素自身将被替换。


    vnode也提供了生命周期钩子，分别是
    init: vdom初始化时
    create: vdom创建时
    prepatch: patch之前
    insert: vdom插入后
    update: vdom更新前
    postpatch: patch之后
    remove: vdom移除时
    destroy: vdom销毁时
</body>
</html>